import { Component, ReactNode, createRef } from 'react'
import { AnimationClip } from 'three'
import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'
import './App.less'
import { Canvas } from './three/Canvas'

interface IState {
  animations: AnimationClip[]
  loopAnimations: AnimationClip[]
  oneAnimations: AnimationClip[]
}
export default class App extends Component<{}, IState> {
  domContainer = createRef<any>()
  canvasRef!: Canvas
  currentAction

  state: Readonly<IState> = {
    animations: [],
    loopAnimations: [],
    oneAnimations: [],
  }

  /** 挂载 */
  componentDidMount(): void {
    this.canvasRef = new Canvas(this.domContainer.current)
    this.canvasRef.onChange((gltf: GLTF) => {
      this.setState({ animations: gltf.animations || [], oneAnimations: [], loopAnimations: [] })
    })

    window.addEventListener('resize', this.resize)

    setTimeout(() => {
      this.canvasRef.loadModel('https://cdn.tanzhijian.net/myBlog/models/RobotExpressive.glb')
    })
  }

  /** 销毁 */
  componentWillUnmount(): void {
    this.canvasRef?.destroy()

    window.removeEventListener('resize', this.resize)
  }

  resize = () => {
    this.canvasRef?.resize()
  }

  loadModel = () => {
    const url = window.prompt('请输入模型url')
    try {
      this.canvasRef?.loadModel(url)
    } catch (error) {
      console.error(error)
      alert(error)
    }
  }

  /** 移动至单次动作集合 */
  moveToOne = () => {
    const all = this.state.animations.filter((item) => item.name !== this.currentAction.name)
    const loop = this.state.loopAnimations.filter((item) => item.name !== this.currentAction.name)
    const one = this.state.oneAnimations.concat(this.currentAction)
    this.setState({
      loopAnimations: loop,
      oneAnimations: one,
      animations: all,
    })
  }

  /** 移动至循环动作集合 */
  moveToLoop = () => {
    const all = this.state.animations.filter((item) => item.name !== this.currentAction.name)
    const one = this.state.oneAnimations.filter((item) => item.name !== this.currentAction.name)
    const loop = this.state.loopAnimations.concat(this.currentAction)
    this.setState({
      loopAnimations: loop,
      oneAnimations: one,
      animations: all,
    })
  }

  render(): ReactNode {
    return (
      <div className='three-action'>
        <div className='CanvasContainer' ref={this.domContainer}></div>
        <div className='animations'>
          <div className='header'>
            <button onClick={this.loadModel}>加载模型</button>

            <div className='light'>
              <label htmlFor='lightInput'>灯光亮度</label>
              <input
                id='lightInput'
                style={{ marginLeft: 10 }}
                type='number'
                placeholder='灯光亮度'
                defaultValue={100}
                onChange={(e) => {
                  this.canvasRef.pointLight.intensity = Number(e.target.value)
                }}
              />
            </div>
          </div>
          <h3>全部动作</h3>
          <div className='all'>
            {this.state.animations.map((item) => {
              return (
                <button
                  key={item.name}
                  className='btn'
                  draggable
                  onDragStart={() => (this.currentAction = item)}
                  onClick={() => {
                    this.canvasRef.fadeToAction(item.name)
                  }}
                >
                  {item.name}
                </button>
              )
            })}
          </div>
          <h3>循环动作</h3>
          <div className='frame loop' onDragOver={(e) => e.preventDefault()} onDrop={this.moveToLoop}>
            {this.state.loopAnimations.map((item) => {
              return (
                <button
                  key={item.name}
                  className='btn'
                  draggable
                  onDragStart={() => (this.currentAction = item)}
                  onClick={() => {
                    this.canvasRef.fadeToAction(item.name, true)
                  }}
                >
                  {item.name}
                </button>
              )
            })}
          </div>

          <h3>单次动作</h3>
          <div className='frame one' onDragOver={(e) => e.preventDefault()} onDrop={this.moveToOne}>
            {this.state.oneAnimations.map((item) => {
              return (
                <button
                  key={item.name}
                  className='btn'
                  draggable
                  onDragStart={() => (this.currentAction = item)}
                  onClick={() => {
                    this.canvasRef.fadeToAction(item.name, false)
                  }}
                >
                  {item.name}
                </button>
              )
            })}
          </div>
        </div>
      </div>
    )
  }
}
